package com.atguigu.ssyx.product.service.impl;


import com.atguigu.ssyx.common.constant.RedisConst;
import com.atguigu.ssyx.common.exception.SsyxException;
import com.atguigu.ssyx.common.result.ResultCodeEnum;
import com.atguigu.ssyx.model.product.SkuAttrValue;
import com.atguigu.ssyx.model.product.SkuImage;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.model.product.SkuPoster;
import com.atguigu.ssyx.mq.constant.MqConst;
import com.atguigu.ssyx.mq.service.RabbitService;
import com.atguigu.ssyx.product.mapper.SkuInfoMapper;
import com.atguigu.ssyx.product.service.SkuAttrValueService;
import com.atguigu.ssyx.product.service.SkuImageService;
import com.atguigu.ssyx.product.service.SkuInfoService;
import com.atguigu.ssyx.product.service.SkuPosterService;
import com.atguigu.ssyx.vo.product.SkuInfoQueryVo;
import com.atguigu.ssyx.vo.product.SkuInfoVo;
import com.atguigu.ssyx.vo.product.SkuStockLockVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * sku信息 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2025-09-13
 */
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {
    //sku图片
    @Autowired
    private SkuImageService skuImageService;
    //sku平台属性
    @Autowired
    private SkuAttrValueService skuAttrValueService;
    //sku海报
    @Autowired
    private SkuPosterService skuPosterService;
    //rabbit
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Override
    public IPage<SkuInfo> selectSkuInfoPage(Page<SkuInfo> skuInfoPrgram, SkuInfoQueryVo skuInfoQueryVo) {
        String skuType = skuInfoQueryVo.getSkuType();
        Long categoryId = skuInfoQueryVo.getCategoryId();
        String keyword = skuInfoQueryVo.getKeyword();
        LambdaQueryWrapper<SkuInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtils.isEmpty(keyword)) {
            queryWrapper.like(SkuInfo::getSkuName, skuType);
        }
        if (!StringUtils.isEmpty(categoryId)) {
            queryWrapper.eq(SkuInfo::getCategoryId, categoryId);
        }
        if (!StringUtils.isEmpty(skuType)) {
            queryWrapper.like(SkuInfo::getSkuType, skuType);
        }
        return baseMapper.selectPage(skuInfoPrgram, queryWrapper);

    }


    // 在Service实现类的方法上添加注解
    @Transactional(rollbackFor = Exception.class) // 发生任何异常都回滚
    @Override
    public void saveSkuInfo(SkuInfoVo skuInfoVo) {
        // 1. 添加sku基本信息
        SkuInfo skuInfo = new SkuInfo();
        BeanUtils.copyProperties(skuInfoVo, skuInfo);
        baseMapper.insert(skuInfo); // 若此处失败，无数据可回滚

        // 2. 保存sku图片
        List<SkuImage> skuImagesList = skuInfoVo.getSkuImagesList();
        if (!CollectionUtils.isEmpty(skuImagesList)) {
            for (SkuImage skuImage : skuImagesList) {
                skuImage.setSkuId(skuInfo.getId());
            }
            skuImageService.saveBatch(skuImagesList); // 若此处失败，回滚步骤1的插入
        }

        // 3. 保存sku海报
        List<SkuPoster> skuPosterList = skuInfoVo.getSkuPosterList();
        if (!CollectionUtils.isEmpty(skuPosterList)) {
            for (SkuPoster skuPoster : skuPosterList) {
                skuPoster.setSkuId(skuInfo.getId());
            }
            skuPosterService.saveBatch(skuPosterList); // 若此处失败，回滚步骤1和2
        }

        // 4. 保存sku平台属性
        List<SkuAttrValue> skuAttrValueList = skuInfoVo.getSkuAttrValueList();
        if (!CollectionUtils.isEmpty(skuAttrValueList)) {
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(skuInfo.getId());
            }
            skuAttrValueService.saveBatch(skuAttrValueList); // 若此处失败，回滚所有步骤
        }
    }

    @Override
    public SkuInfoVo getSkuInfo(Long id) {
        SkuInfoVo skuInfoVo = new SkuInfoVo();
        //根据id查询sku基本信息
        SkuInfo skuInfo = baseMapper.selectById(id);
        //根据id查询商品的图片列表
         List<SkuImage>  imageListBySkuId= skuImageService.getImageListBySkuId(id);
        //根据id查询商品的海报列表
         List<SkuPoster>  posterListBySkuId=  skuPosterService.getPosterListBySkuId(id);
        //根据id查询商品的属性信息列表
        List<SkuAttrValue> skuAttrValueList=  skuAttrValueService.getAttrValueListBySkuId(id);

        //最终封装
        BeanUtils.copyProperties(skuInfo, skuInfoVo);
        skuInfoVo.setSkuAttrValueList(skuAttrValueList);
        skuInfoVo.setSkuPosterList(posterListBySkuId);
        skuInfoVo.setSkuImagesList(imageListBySkuId);
        return skuInfoVo;
    }
    //修改sku信息
    @Transactional(rollbackFor = Exception.class) // 发生任何异常都回滚
    @Override
    public void updateSkuInfo(SkuInfoVo skuInfoVo) {
        //修改基本信息
        //把skuinfovo->skuinfo
        SkuInfo skuInfo = new SkuInfo();
        BeanUtils.copyProperties(skuInfoVo, skuInfo);
        baseMapper.updateById(skuInfo);

        //取到skuinfovo的id
        Long SKUid = skuInfoVo.getId();
        //修改海报信息
        //先删除
        LambdaQueryWrapper<SkuPoster> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SkuPoster::getSkuId, SKUid);
        skuPosterService.remove(queryWrapper);
        //后添加
        List<SkuPoster> skuPosterList = skuInfoVo.getSkuPosterList();
        if (!CollectionUtils.isEmpty(skuPosterList)) {
            for (SkuPoster skuPoster : skuPosterList) {
                skuPoster.setSkuId(SKUid);
            }
            skuPosterService.saveBatch(skuPosterList); // 若此处失败，回滚步骤1和2
        }
        //修改图片信息
        //先删除
        LambdaQueryWrapper<SkuImage> queryWrapperImage = new LambdaQueryWrapper<>();
        queryWrapperImage.eq(SkuImage::getSkuId, SKUid);
        skuImageService.remove(queryWrapperImage);
        //后添加
        List<SkuImage> skuImagesList = skuInfoVo.getSkuImagesList();
        if (!CollectionUtils.isEmpty(skuImagesList)) {
            for (SkuImage skuImage : skuImagesList) {
                skuImage.setSkuId(SKUid);
            }
            skuImageService.saveBatch(skuImagesList); // 若此处失败，回滚步骤1的插入
        }

        //修改商品属性信息
        //先删除
      LambdaQueryWrapper<SkuAttrValue> queryWrapperAttrValue = new LambdaQueryWrapper<>();
        queryWrapperAttrValue.eq(SkuAttrValue::getSkuId, SKUid);
        skuAttrValueService.remove(queryWrapperAttrValue);

        //后添加
        List<SkuAttrValue> skuAttrValueList = skuInfoVo.getSkuAttrValueList();
        if (!CollectionUtils.isEmpty(skuAttrValueList)) {
            for (SkuAttrValue skuAttrValue : skuAttrValueList) {
                skuAttrValue.setSkuId(SKUid);
            }
            skuAttrValueService.saveBatch(skuAttrValueList); // 若此处失败，回滚所有步骤
        }
    }

    @Override
    public void check(Long skuid, Integer status) {
        SkuInfo skuInfo = baseMapper.selectById(skuid);
        skuInfo.setCheckStatus(status);
        baseMapper.updateById(skuInfo);
    }

    @Override
    public void publish(Long skuid, Integer status) {
        if (status==1){//上架
            SkuInfo skuInfo = baseMapper.selectById(skuid);
            skuInfo.setPublishStatus(status);
            baseMapper.updateById(skuInfo);
            //整合mq把数据同步到es里面
            rabbitService.sendMessage(MqConst.EXCHANGE_GOODS_DIRECT ,
                    MqConst.ROUTING_GOODS_UPPER,
                    skuid);
        }else{//下架
            SkuInfo skuInfo = baseMapper.selectById(skuid);
            skuInfo.setPublishStatus(status);
            baseMapper.updateById(skuInfo);

            //整合mq把数据同步到es里面
            rabbitService.sendMessage(MqConst.EXCHANGE_GOODS_DIRECT,
                    MqConst.ROUTING_GOODS_LOWER,
                    skuid);
        }

    }

    @Override
    public void isNewPerson(Long skuid, Integer status) {
        SkuInfo skuInfoUp = new SkuInfo();
        skuInfoUp.setId(skuid);
        skuInfoUp.setIsNewPerson(status);
        baseMapper.updateById(skuInfoUp);
    }
    //根据skuid列表获取sku信息
    @Override
    public List<SkuInfo> findSkuInfoList(List<Long> skuIds) {
        if (CollectionUtils.isEmpty(skuIds)) {
            return new ArrayList<>();
        }
        List<SkuInfo> skuInfoList = baseMapper.selectBatchIds(skuIds);
        return skuInfoList;
    }
    //根据关键字查询sku匹配的内容列表
    @Override
    public List<SkuInfo> findSkuInfoByKeyword(String keyword) {
        List<SkuInfo> skuInfoList = baseMapper.selectList(
                new LambdaQueryWrapper<SkuInfo>().like(SkuInfo::getSkuName, keyword)
        );
        return skuInfoList;
    }
    //获取新人专享
    @Override
    public List<SkuInfo> findNewPersonList() {
        //条件1: is_new_person=1
        //条件2: publish_status=1
        //条件3:显示其中的三个
        Page<SkuInfo> pageparam = new Page(1,3);
        LambdaQueryWrapper<SkuInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SkuInfo::getIsNewPerson,1);
        queryWrapper.eq(SkuInfo::getIsNewPerson,1);
        queryWrapper.orderByDesc(SkuInfo::getStock);//库存排序
        //调用方法
        Page<SkuInfo> skuInfoPage = baseMapper.selectPage(pageparam, queryWrapper);
        List<SkuInfo> records = skuInfoPage.getRecords();
        return records;
    }
    //根据skuId获取sku信息
    @Override
    public SkuInfoVo getSkuInfoVo(Long skuId) {
        SkuInfoVo skuInfoVo = new SkuInfoVo();
        //根据skuId查询skuInfo
        SkuInfo skuInfo = baseMapper.selectById(skuId);
        //根据skuId查询sku图片
        List<SkuImage> imageList = skuImageService.getImageListBySkuId(skuId);
        //根据skuId查询sku海报
        List<SkuPoster> posterList = skuPosterService.getPosterListBySkuId(skuId);
        //根据skuId查询sku属性
        List<SkuAttrValue> attrValueList = skuAttrValueService.getAttrValueListBySkuId(skuId);
        //封装
        BeanUtils.copyProperties(skuInfo,skuInfoVo);
        skuInfoVo.setSkuImagesList(imageList);
        skuInfoVo.setSkuPosterList(posterList);
        skuInfoVo.setSkuAttrValueList(attrValueList);
        return skuInfoVo;
    }

    @Override
    public Boolean checkAndLock(List<SkuStockLockVo> skuStockLockVoList, String orderNo) {
        //1.判断skuStockeLockVoList集合是否为空
        if(CollectionUtils.isEmpty(skuStockLockVoList)){
            throw  new SsyxException(ResultCodeEnum.DATA_ERROR);
        }
        //2.遍历skuStockeLockVoList得到每一个商品，验证库存并锁定库存 具备原子性
        skuStockLockVoList.stream().forEach(skuStockLockVo -> {
            this.checkLock(skuStockLockVo);
        });
        //3.只要有一个商品锁定失败，所有锁定成功的商品都要解锁
        boolean flag = skuStockLockVoList.stream().anyMatch(
                skuStockLockVo -> !skuStockLockVo.getIsLock()
        );
        if(flag){
          //  所有锁定成功的商品都要解锁
            skuStockLockVoList.stream().filter(
                    SkuStockLockVo::getIsLock
            ).forEach(skuStockLockVo -> {
                baseMapper.unlockStock(skuStockLockVo.getSkuId(),skuStockLockVo.getSkuNum());
            });
            // 返回失败的状态
            return false;
        }
        //4.如果所有商品都锁定成功了，redis缓存相关数据，为了方便解锁和减库存
        redisTemplate.opsForValue()
                .set(RedisConst.SROCK_INFO+orderNo,skuStockLockVoList);


        return true;
    }
    //扣减库存成功，更新订单状态
    @Override
    public void minusStock(String orderNo) {
       List<SkuStockLockVo> skuStockLockVoList=(List<SkuStockLockVo>)redisTemplate.opsForValue().get(RedisConst.SROCK_INFO+orderNo);
        if(CollectionUtils.isEmpty(skuStockLockVoList)){
            return;
        }
        //遍历集合得到每一个对象，减库存
        skuStockLockVoList.forEach(skuStockLockVo -> {
           baseMapper.minusStock(skuStockLockVo.getSkuId(),skuStockLockVo.getSkuNum());
        });
        //删除redis数据
        redisTemplate.delete(RedisConst.SROCK_INFO+orderNo);
    }

    //2.遍历skuStockeLockVoList得到每一个商品，验证库存并锁定库存 具备原子性
    private void checkLock(SkuStockLockVo skuStockLockVo) {
        //获取锁
        //公平锁
        RLock rLock = this.redissonClient.getFairLock(RedisConst.SKUKEY_PREFIX + skuStockLockVo.getSkuId());
        //加锁
        rLock.lock();

        try{
            //验证库存  查询数据库
            SkuInfo skuInfo=
                    baseMapper.checkStock(skuStockLockVo.getSkuId(),skuStockLockVo.getSkuNum());
            //判断
            //如果没有满足条件的商品，设置islock值为空，返回
            if(skuInfo==null){
                skuStockLockVo.setIsLock(false);
                return;
            }
            //有满足条件的商品
            //锁定库存 update
           Integer rows=
                   baseMapper.lockStock(skuStockLockVo.getSkuId(),skuStockLockVo.getSkuNum());
            if(rows==1){
                skuStockLockVo.setIsLock(true);
            }
        }finally {
            //解锁
            rLock.unlock();
        }
    }
}